let _Vue = null
const HISTORY = 'history'

export default class VueRouter {
  static install(Vue) {
    // 1.判断当前插件是否已经被安装
    if(VueRouter.install.installed) {
      return
    }
    VueRouter.install.installed = true
    // 2.把Vue构造函数记录到全局变量
    _Vue = Vue
    // 3.把创建Vue实例时候传入的router对象注入到Vue实例上
    // 混入
    _Vue.mixin({
      beforeCreate(){
        if(this.$options.router) {
          _Vue.prototype.$router = this.$options.router
          this.$options.router.init()
        }
      }
    })
  }

  constructor(options) {
    this.options = options
    this.mode = options.mode || HISTORY
    this.routeMap = {}
    this.data = _Vue.observable({
      current: '/'
    })
  }

  init(){
    this.createRouteMap()
    this.initComponents(_Vue)
    this.inieEvent()
  }

  createRouteMap(){
    // 遍历所有的路由规则，把路由规则解析成键值对的形式，存储在routeMap中
    this.options.routes.forEach(route => {
      this.routeMap[route.path] = route.component
    })
  }

  initComponents(Vue) {
    const self = this
    Vue.component('router-link', {
      props: {
        to: String
      },
      // 如果需要在运行时编译template，则需要在vue.config.js中配置runtimeCompiler为true
      // template: '<a :href="to"><slot></slot></a>'
      render(h) {
        let to = self.mode === HISTORY ? this.to : `#${this.to}`
        return h('a', {
          attrs: {
            href: to
          },
          on: {
            click: this.clickHandler
          }
        }, [this.$slots.default])
      },
      methods: {
        clickHandler(e){
          if(this.$router.mode === HISTORY) {
            history.pushState({}, '', this.to)
            this.$router.data.current = this.to
            e.preventDefault()
          } else {
            // hash模式
            let to = `#${this.to}`
            history.pushState({}, '', to)
            this.$router.data.current = to
            e.preventDefault()
          }      
        }
      }
    })

    Vue.component('router-view', {
      render(h) {
        let hash = window.location.hash;
        let dataCurrent = self.data.current;
        if(hash.length > 2) {
          dataCurrent = hash // hash 模式刷新情况
        }
        let current = dataCurrent.startsWith('#') ? dataCurrent.slice(1) : dataCurrent
        const component = self.routeMap[current]
        return h(component)
      }
    })
  }

  inieEvent(){
    window.addEventListener('popstate', () => {
      this.data.current = window.location.pathname
    })

    window.addEventListener('hashchange', () => {
      this.data.current = window.location.hash.slice(1)
    })
  }
}